/**
 * 
 */
package org.youisoft.summer.evaluator.function.control;

import org.youisoft.summer.evaluator.InvokeException;
import org.youisoft.summer.evaluator.context.CalContext;
import org.youisoft.summer.evaluator.function.AbstractFunction;
import org.youisoft.summer.evaluator.operator.Operator;
import org.youisoft.summer.evaluator.operator.base.ClosureOperator;
import org.youisoft.summer.evaluator.operator.base.NumberOperator;

/**
 * @author zijiang.jl
 *
 */
public class LoopFunction extends AbstractFunction{

	@Override
	protected boolean checkOperator(int index, Operator<?> operator) {
		if(index==0&&ClosureOperator.class.isAssignableFrom(operator.getClass())) return true;
		if(index==1&&NumberOperator.class.isAssignableFrom(operator.getClass())) return true;
		return false;
	}

	@Override
	public <C,R,P> Operator<?> doInvoke(CalContext<C,R,P> context,Operator<?>... operator) throws InvokeException{
		final ClosureOperator call=ClosureOperator.class.cast(operator[0]);
		int cnt=NumberOperator.class.cast(operator[1]).value().intValue();
		if(cnt<0){
			while(true){
				try{
					if(context.isNeedBreak()) break;
					if(context.isNeedContinue()) continue;
					if(context.isNeedPause()) Thread.sleep(context.getPauseTime());
					call.execute(context);
				}catch(java.lang.Throwable t){
					logger.error(t.getMessage());
					logger.debug(t);
				}

			}
		}
		for(int i=0;i<cnt;i++){
			try{
				if(context.isNeedBreak()) break;
				if(context.isNeedContinue()) continue;
				if(context.isNeedPause()) Thread.sleep(context.getPauseTime());
				call.execute(context);
			}catch(java.lang.Throwable t){
				logger.error(t.getMessage());
				logger.debug(t);
			}

		}
		return Operator.nullInstance;
	}

	@Override
	protected int minOperatorCount() {
		return 2;
	}
	
}